use crate::{mathml, svg, HtmlParser, ParserConfig};
use std::error::Error;

#[test]
fn test_svg_parsing() -> Result<(), Box<dyn Error>> {
    let html = r#"
    <html>
    <body>
        <svg width="100" height="100" xmlns="http://www.w3.org/2000/svg">
            <circle cx="50" cy="50" r="40" stroke="black" stroke-width="2" fill="red" />
            <rect x="10" y="10" width="30" height="30" fill="blue" />
        </svg>
    </body>
    </html>
    "#;

    let parser = HtmlParser::new(ParserConfig::default());
    let dom = parser.parse(html)?;

    // 查找SVG元素
    let svg_elements = parser.query_selector(&dom, "svg")?;
    assert_eq!(svg_elements.len(), 1, "应该找到一个SVG元素");

    let svg_element = svg_elements[0];
    assert!(svg_element.is_svg_element(), "该元素应该被识别为SVG元素");
    assert_eq!(
        svg_element.get_namespace(),
        Some(svg::SVG_NAMESPACE),
        "命名空间应该正确"
    );

    // 检查SVG子元素
    let circle_elements = parser.query_selector(svg_element, "circle")?;
    assert_eq!(circle_elements.len(), 1, "应该找到一个circle元素");
    assert!(
        circle_elements[0].is_svg_element(),
        "circle应该在SVG命名空间中"
    );

    let rect_elements = parser.query_selector(svg_element, "rect")?;
    assert_eq!(rect_elements.len(), 1, "应该找到一个rect元素");
    assert!(rect_elements[0].is_svg_element(), "rect应该在SVG命名空间中");

    // 测试序列化
    let serialized = parser.to_html(&dom, true);
    assert!(serialized.contains("<svg"), "序列化结果应该包含SVG标签");
    assert!(
        serialized.contains("<circle"),
        "序列化结果应该包含circle标签"
    );
    assert!(serialized.contains("<rect"), "序列化结果应该包含rect标签");

    Ok(())
}

#[test]
fn test_mathml_parsing() -> Result<(), Box<dyn Error>> {
    let html = r#"
    <html>
    <body>
        <math xmlns="http://www.w3.org/1998/Math/MathML">
            <mrow>
                <mi>x</mi>
                <mo>+</mo>
                <mfrac>
                    <mn>1</mn>
                    <mn>2</mn>
                </mfrac>
            </mrow>
        </math>
    </body>
    </html>
    "#;

    let parser = HtmlParser::new(ParserConfig::default());
    let dom = parser.parse(html)?;

    // 查找MathML元素
    let math_elements = parser.query_selector(&dom, "math")?;
    assert_eq!(math_elements.len(), 1, "应该找到一个math元素");

    let math_element = math_elements[0];
    assert!(
        math_element.is_mathml_element(),
        "该元素应该被识别为MathML元素"
    );
    assert_eq!(
        math_element.get_namespace(),
        Some(mathml::MATHML_NAMESPACE),
        "命名空间应该正确"
    );

    // 检查MathML子元素
    let mrow_elements = parser.query_selector(math_element, "mrow")?;
    assert_eq!(mrow_elements.len(), 1, "应该找到一个mrow元素");

    let mi_elements = parser.query_selector(math_element, "mi")?;
    assert_eq!(mi_elements.len(), 1, "应该找到一个mi元素");

    let mfrac_elements = parser.query_selector(math_element, "mfrac")?;
    assert_eq!(mfrac_elements.len(), 1, "应该找到一个mfrac元素");

    // 验证mfrac有两个子元素
    let mfrac = mfrac_elements[0];
    assert_eq!(mfrac.children.len(), 2, "mfrac应该有两个子元素");

    // 测试序列化
    let serialized = parser.to_html(&dom, true);
    assert!(serialized.contains("<math"), "序列化结果应该包含math标签");
    assert!(serialized.contains("<mrow"), "序列化结果应该包含mrow标签");
    assert!(serialized.contains("<mfrac"), "序列化结果应该包含mfrac标签");

    Ok(())
}

#[test]
fn test_mixed_namespaces() -> Result<(), Box<dyn Error>> {
    let html = r#"
    <html>
    <body>
        <div>
            <svg width="100" height="100">
                <circle cx="50" cy="50" r="40" fill="red" />
                <text x="50" y="50">SVG Text</text>
            </svg>
            <p>HTML paragraph</p>
            <math>
                <mi>a</mi>
                <mo>+</mo>
                <mi>b</mi>
            </math>
        </div>
    </body>
    </html>
    "#;

    let parser = HtmlParser::new(ParserConfig::default());
    let dom = parser.parse(html)?;

    // 查找不同命名空间的元素
    let div_elements = parser.query_selector(&dom, "div")?;
    assert_eq!(div_elements.len(), 1, "应该找到一个div元素");
    assert_eq!(
        div_elements[0].get_namespace(),
        None,
        "HTML元素没有命名空间"
    );

    let svg_elements = parser.query_selector(&dom, "svg")?;
    assert_eq!(svg_elements.len(), 1, "应该找到一个svg元素");
    assert!(
        svg_elements[0].is_svg_element(),
        "svg元素应该在SVG命名空间中"
    );

    let math_elements = parser.query_selector(&dom, "math")?;
    assert_eq!(math_elements.len(), 1, "应该找到一个math元素");
    assert!(
        math_elements[0].is_mathml_element(),
        "math元素应该在MathML命名空间中"
    );

    // 测试序列化
    let serialized = parser.to_html(&dom, true);
    assert!(serialized.contains("<div"), "序列化结果应该包含div标签");
    assert!(serialized.contains("<svg"), "序列化结果应该包含svg标签");
    assert!(serialized.contains("<math"), "序列化结果应该包含math标签");

    Ok(())
}
